class Leaf (nodeId : String) {
	var smaller = List[NodeEntry]()
	var larger = List[NodeEntry]()
	val maxLeafSize = 8
	var lastModified = System.currentTimeMillis()   
	
	def add(node : NodeEntry) : Boolean ={
	  val comparison = node.getNodeId.compareTo(nodeId)
	  var addedNode = false;
	  
	  if (comparison < 0){
	    val duplicate = smaller.contains(node)
	    
	    if (!duplicate && smaller.length < maxLeafSize){
	      smaller ++= List(node)
	      smaller = smaller.sortBy(x => x.getNodeId)
	      addedNode = true
	    }
	    else if (!duplicate && node.getNodeId.compareTo(smaller(0).getNodeId) > 0){
	      smaller ++= List(node)
	      smaller = smaller.sortBy(x => x.getNodeId)
	      smaller = smaller.drop(1)
	      addedNode = true
	    }
	  }
	  else if (comparison > 0){
	    val duplicate = larger.contains(node)
	    
	    if (!duplicate && larger.length < maxLeafSize){
	      larger ++= List(node)
	      larger = larger.sortBy(x => x.getNodeId)
	      addedNode = true
	    }
	    else if (!duplicate && node.getNodeId.compareTo(larger.last.getNodeId) < 0){
	      larger ++= List(node)
	      larger = larger.sortBy(x => x.getNodeId)
	      larger = larger.dropRight(1)
	      addedNode = true
	    }
	  }
	  else{
	    //println("Leaf: same nodeId found when adding node")
	  }
	  
	  if (addedNode){
	    lastModified = System.currentTimeMillis()  
	  }
	  
	  addedNode
	}
	
	def inRange(nodeId : String) : Boolean = {
	  var nodeInRange = false
	  if (nodeId.compareTo(this.nodeId) < 0 && smaller.length > 0 && nodeId.compareTo(smaller(0).getNodeId) >= 0){
	    nodeInRange = true
	  }
	  else if (nodeId.compareTo(this.nodeId) > 0 && larger.length > 0 && nodeId.compareTo(larger.last.getNodeId) <= 0){
	    nodeInRange = true
	  }
	  
	  nodeInRange
	}
	
	def getClosestNode(key : String) : NodeEntry ={
	  var node = new NodeEntry
	  var diff = new java.math.BigInteger("0")
	  for (i <- 0 to smaller.length - 1){
	  	val d = Utils.getNodeDiff(smaller(i).getNodeId, key)
	  	if (i == 0 || d.compareTo(diff) < 0){
	  	  diff = d
	  	  node = smaller(i)
	  	}
	  }
	  
	  for (i <- 0 to larger.length - 1){
	    val d = Utils.getNodeDiff(larger(i).getNodeId, key)
	  	if (node.isEmpty || d.compareTo(diff) < 0){
	  	  diff = d
	  	  node = larger(i)
	  	}
	  }
	  
	  val d = Utils.getNodeDiff(nodeId, key)
      if (node.isEmpty || d.compareTo(diff) < 0){
	  	 node = null
	  }
	  node  
	}
	
	def CopyLeaf(leaf : Leaf, node : NodeEntry){
	  for (n <- leaf.smaller){
	    if (n != null){
	      add(n)
	    }
	  }
	  for (n <- leaf.larger){
	    if (n != null){
	      add(n)
	    }
	  }
	  
	  add(node)
	}
	
	def print(){
	  println("leaf for: " + nodeId)
	  println("smaller")
	  var s = ""
	  smaller.foreach(x => s = s + x.getNodeId + ", ")
	  println(s)
	  
	  println("larger")
	  var l = ""
	  larger.foreach(x => l = l + x.getNodeId + ", ")
	  println(l)
	}
	
	def toJson() : String = {
	  var json = "{"
	  json += "\"nodeId\": \"" + nodeId + "\","
	  
	  json += "\"smaller\":["
	  for (i <- 0 to smaller.length-1){
	    json += smaller(i).toJson
	    if (i < smaller.length-1) { json += ","}
	  }
	  json += "],"
	  
	  json += "\"larger\":["
	  for (i <- 0 to larger.length-1){
	    json += larger(i).toJson 
	    if (i < larger.length-1) { json += ","}
	  }
	  json += "]"
	    
	  json += "}"  
	  json
	}
	
	override def toString = "leaf"
}